package sg.edu.nus.iss.jass.datastore.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import sg.edu.nus.iss.jass.datastore.AbstractFileStorage;
import sg.edu.nus.iss.jass.datastore.BaseDTO;
import sg.edu.nus.iss.jass.datastore.IDataMapper;

/**
 * <p>An implementation to store data in java Properties format.</p>
 * 
 * Data transformation between object and properties format(key/value) is delegated to {@link IDataMapper}. 
 * Every key of object will append '_{id}'. {id} is the identifier of given object.
 * 
 * @author WANG DAYONG
 *
 */
public class PropertiesStorage extends AbstractFileStorage {

	
	/**
	 * The object that is responsible to transform data between java Properties and java object
	 */
	private IDataMapper dataMapper;
	
	/**
	 * Constructor
	 * @param rootPath the root path of the storage on file system
	 * @param dataMapper the mapper to transform data between java properties format to java bean
	 */
	public PropertiesStorage(String rootPath, IDataMapper dataMapper) {

		super(rootPath);
		this.dataMapper = dataMapper;
	}


	@Override
	protected byte[] getBytesFromObject(List<? extends BaseDTO> saveObj) throws IOException {

		if (saveObj==null) {
			return null;
		}
		Properties prop = dataMapper.mapObject2Properties(saveObj);

		ByteArrayOutputStream byteout = null;
		try {
			byteout = new ByteArrayOutputStream();
			prop.store(byteout, null);
			return byteout.toByteArray();
		} finally {
			if (byteout!=null)
				byteout.close();
		}
	}


	@Override
	protected List<? extends BaseDTO> loadObjectFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {

		if (bytes==null||bytes.length==0) {
			return null;
		}
		Properties prop = new Properties();
		ByteArrayInputStream byteInputStream = null;

		try {
			byteInputStream = new ByteArrayInputStream(bytes);
			prop.load(byteInputStream);
			return (List<? extends BaseDTO>)dataMapper.mapProperties2Object(prop);
		} catch (IOException e) {
			throw e;
		} finally {
			if (byteInputStream!=null)
				byteInputStream.close();
		}
	}

	@Override
	protected List<? extends BaseDTO> loadObjectFromFile(String fileName) throws IOException, ClassNotFoundException {

		Properties prop = new Properties();
		FileInputStream fin = null;
		try {
			fin = new FileInputStream(new File(getRealPath(fileName)));
			prop.load(fin);
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
			return null;
		} catch (IOException ex) {
			throw ex;
		} finally {
			if (fin!=null)
				fin.close();
		}

		return (List<? extends BaseDTO>) dataMapper.mapProperties2Object(prop);
	}

	

	@Override
	protected void writeObject2File(String fileName, List<? extends BaseDTO> obj) throws IOException {

		Properties prop = dataMapper.mapObject2Properties(obj);

		FileOutputStream fout = null;
		try {
			fout = new FileOutputStream(new File(getRealPath(fileName)));
			prop.store(fout, null);
		} catch (IOException ex) {
			throw ex;
		} finally {
			if (fout!=null)
				fout.close();
		}
	}

}
